#include <scdl/parser/Symbol.hpp>

#include <cstdlib>
#include <cstring>
#include <iostream>

using std::cout;
using namespace scdl;

Symbol::Symbol()
        : filename(0), _line(0), _col(0),
          typed(false), type(0), level(LEVEL_ROOT)
{
}

Symbol::~Symbol()
{
        if (filename)
                free(filename);
        safe_unref(type);
}

SymbolCategory Symbol::getCategory()
{
        return CATEGORY_TBD;
}

void Symbol::setPosition(const char *file, int line, int col)
{
        if (filename)
                free(filename);

        filename = strdup(file);
        this->_line = line;
        this->_col = col;
}

void Symbol::setPosition(Symbol *sym)
{
        if (filename)
                free(filename);

        filename = strdup(sym->file());
        _line = sym->line();
        _col = sym->column();
}

const char *Symbol::file()
{
        return filename;
}

int Symbol::line()
{
        return _line;
}

int Symbol::column()
{
        return _col;
}

void Symbol::prettyPrint(bool verbose)
{
        cout << "<Symbol at " << filename << ":" << _line << ":" << _col << ">";
}

void Symbol::setType(Symbol *sym)
{
        if (!sym)
                return;

        SymbolTypeLevel typeLevel = sym->getTypeLevel();
        if (typeLevel >= LEVEL_OBJECT)
                return;

        this->type = sym;
        typed = true;
        sym->ref();
        level = static_cast<SymbolTypeLevel>(typeLevel + 1);
}

Symbol *Symbol::getType(Symbol *expected)
{
        if (!typed)
                determineType(expected);
        return type;
}

void Symbol::determineType(Symbol *expected)
{
        typed = true;
}

SymbolTypeLevel Symbol::getTypeLevel()
{
        return level;
}
